const std = @import("std");
const awtk = @import("awtk");
const mvvm = @import("../mvvm.zig");
const object = @import("../object.zig");
const user_model = @import("../models/user.zig");
const model_list = @import("../model_list.zig");

const c = awtk.c;

pub const UsersVM = struct {
    name: awtk.String = undefined,
    cfg: struct {
        age: u8,
        gender: user_model.Gender,
    } = .{
        .age = 0,
        .gender = .Male,
    },
    users: Users = undefined,

    const Users = model_list.ModelList(user_model.User);
    const Self = @This();

    pub fn init(self: *Self) !void {
        std.log.debug("{s}.{s}", .{ awtk.baseTypeName(@This()), @src().fn_name });
        self.name = awtk.String.init(8);
        try self.users.init();
    }

    pub fn deinit(self: *Self) void {
        std.log.debug("{s}.{s}", .{ awtk.baseTypeName(@This()), @src().fn_name });
        self.name.deinit();
        self.users.deinit();
    }

    // 虚拟property: isGenderBalance
    pub fn getIsGenderBalance(self: Self, _: []const u8, v: *awtk.Value) c.ret_t {
        var male_count: u32 = 0;
        var female_count: u32 = 0;
        for (self.users.models.items) |item| {
            if (item.gender == .Male) {
                male_count += 1;
            } else {
                female_count += 1;
            }
        }

        _ = c.value_set_bool(v, male_count == female_count);
        return c.RET_OK;
    }

    // 虚拟property: languageId
    pub fn getLanguageId(_: Self, _: []const u8, v: *awtk.Value) c.ret_t {
        _ = c.value_set_uint8(v, @intFromEnum(awtk.getLanguage()));
        return c.RET_OK;
    }

    // 设置虚拟property: languageId
    pub fn setLanguageId(_: *Self, _: []const u8, v: *const awtk.Value) c.ret_t {
        const language = awtk.Language.fromInt(c.value_uint8(v)) catch |e| {
            std.log.err("{s}.{s}: {s}", .{ awtk.baseTypeName(Self), @src().fn_name, @errorName(e) });
            return c.RET_BAD_PARAMS;
        };

        if (language != awtk.getLanguage()) {
            awtk.setLanguage(language) catch |e| {
                std.log.err("{s}.{s}: {s}", .{ awtk.baseTypeName(Self), @src().fn_name, @errorName(e) });
                return c.RET_FAIL;
            };
        }

        return c.RET_OK;
    }

    pub fn addAge(self: *Self) !awtk.Notify {
        self.cfg.age += 1;
        return .PropertyChanged;
    }

    pub fn canAddAge(self: Self) bool {
        return self.cfg.age < 5;
    }

    pub fn subAge(self: *Self) !awtk.Notify {
        self.cfg.age -= 1;
        return .PropertyChanged;
    }

    pub fn canSubAge(self: Self) bool {
        return self.cfg.age > 0;
    }

    pub fn addSomeAges(self: *Self, args: ?[:0]const u8) !awtk.Notify {
        const str = args orelse return .Fail;
        const v = try std.fmt.parseInt(u8, str, 10);

        self.cfg.age += v;
        return .PropertyChanged;
    }

    pub fn append(self: *Self) !awtk.Notify {
        var user = user_model.User{};
        user.init();

        user.age = self.cfg.age;
        user.gender = self.cfg.gender;
        const user_name = self.name.str();
        try user.setName(user_name);

        std.log.debug("append user: {f}", .{user});
        try self.users.append(&user);

        return .ItemsChanged;
    }

    pub fn canAppend(self: Self) bool {
        return self.name.len() > 0;
    }

    pub fn remove(self: *Self, args: ?[:0]const u8) !awtk.Notify {
        //std.log.debug("remove args: {s}", .{args orelse "(null)"});
        var kvs = mvvm.StringArgs.init(args);
        defer kvs.deinit();

        const item_index = try kvs.get("index", u32);
        const users: *Users = &self.users;
        try users.remove(@intCast(item_index));

        return .ItemsChanged;
    }

    pub fn edit(self: *Self, cargs: ?[:0]const u8) !awtk.Notify {
        var kvs = mvvm.StringArgs.init(cargs);
        defer kvs.deinit();

        const item_index = try kvs.get("index", u32);
        const users: *Users = &self.users;

        try users.navigateWithItem("win_edit_user", item_index);
        return .Ok;
    }
};
